package com.wanhe.mealbookmodule.presenter;

import android.content.Context;
import android.text.TextUtils;

import com.google.gson.Gson;
import com.orhanobut.logger.Logger;
import com.wanhe.base.injector.module.BaseApplicationModule;
import com.wanhe.base.model.base.SallOutDish;
import com.wanhe.base.model.disgn.DSFile;
import com.wanhe.base.model.disgn.ViewItem;
import com.wanhe.base.model.entity.DesignEntity;
import com.wanhe.base.model.entity.SellOutResultEntity;
import com.wanhe.base.model.holder.CustomPageHolder;
import com.wanhe.base.model.holder.FileHolder;
import com.wanhe.base.model.holder.SallOutHolder;
import com.wanhe.base.util.SPUtils;
import com.wanhe.mealbookmodule.adapter.CommonAdapter;
import com.wanhe.mealbookmodule.adapter.views.IListViewAdapter;
import com.wanhe.base.model.base.Dish;
import com.wanhe.base.model.base.DishesType;
import com.wanhe.base.model.disgn.CatalogViewModel;
import com.wanhe.base.model.disgn.PageViewModel;
import com.wanhe.base.model.entity.BaseResultEntity;
import com.wanhe.base.model.entity.DishesTypeDetailEntity;
import com.wanhe.base.model.holder.DishConfHolder;
import com.wanhe.base.model.holder.DishHolder;
import com.wanhe.base.model.holder.DishTypeHolder;
import com.wanhe.mealbookmodule.presenter.views.ILoadingView;
import com.wanhe.base.util.ObjectUtil;

import java.util.ArrayList;
import java.util.List;

import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.functions.Predicate;
import io.reactivex.schedulers.Schedulers;

/**
 * Created by cdj on 2017/6/22.
 */

public class MealBookPresenter extends BaseAdapterPresenter {

    private final IListViewAdapter<PageViewModel> mPagerAdapter;
    private final ILoadingView mView;
    private final BaseApplicationModule.RxBus mBus;
    private final CommonAdapter mTypeAdapter;

    /**
     * Methor Name:MealBookPresenter<br/>
     * Package Name:com.wanhe.mealbookmodule.presenter<br/>
     * Date:2017/8/1 15:03<br/>
     * author:chendeji<br/>
     * desc: 菜品数据处理层<br/>
     * Copyright (c) 2017/8/1, 781571323@qq.com All Rights Reserved.
     *
     * @param view        带有加载流程的view
     * @param adapter     菜品页面的数据适配器
     * @param typeAdapter 菜品分类布局的数据适配器
     * @param bus         应用的事件分发器
     * @return
     */
    public MealBookPresenter(ILoadingView view, IListViewAdapter<PageViewModel> adapter,
                             CommonAdapter typeAdapter, BaseApplicationModule.RxBus bus) {
        this.mView = view;
        this.mPagerAdapter = adapter;
        this.mTypeAdapter = typeAdapter;
        this.mBus = bus;
    }

    public void showMealBookPages(Context context) {
        if (loading(context, mView) || SPUtils.getIsDemoSchema()) {
            loadMealDishData();
        }
    }

    private void loadMealDishData() {
        /**
         *
         * 由朝勋提供关于全量菜品的缓存数据
         *
         * @author 陈德基
         * @time 2017/6/23 14:31
         */
        String cacheDishData = SPUtils.getAllDish();
        Logger.d("===cacheDishData=="+cacheDishData);
        if (TextUtils.isEmpty(cacheDishData)) {
            loadFailed(mView, "菜品数据为空");
            return;
        }

        Observable.just(cacheDishData)
                .flatMap(new Function<String, ObservableSource<DishesType>>() {
                    @Override
                    public ObservableSource<DishesType> apply(@NonNull String s) throws Exception {
                        DishesTypeDetailEntity dishesTypeDetailEntity = new Gson().fromJson(s,
                                DishesTypeDetailEntity.class);
                        if (ObjectUtil.checkObject(dishesTypeDetailEntity)
                                && dishesTypeDetailEntity.resultType == BaseResultEntity.SUCCESS) {
                            return Observable.fromIterable(dishesTypeDetailEntity.DishesTypeDetail);
                        }
                        throw new IllegalArgumentException("dish data return err");
                    }
                }).filter(new Predicate<DishesType>() {
            @Override
            public boolean test(@NonNull DishesType dishesType) throws Exception {
                return ObjectUtil.checkObjectList(dishesType.getDishes());
            }
        }).flatMap(new Function<DishesType, ObservableSource<Dish>>() {
            DishTypeHolder typeHolder = DishTypeHolder.getInstance();

            @Override
            public ObservableSource<Dish> apply(@NonNull DishesType dishesType)
                    throws Exception {
                typeHolder.put(dishesType.getTypeGuid(), dishesType);
                for (int i = 0; i < dishesType.getDishes().size(); i++) {
                    dishesType.getDishes().get(i).dish_type_guid = dishesType.getTypeGuid();
                }
                return Observable.fromIterable(dishesType.getDishes());
            }
        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<Dish>() {
                    DishHolder holder = DishHolder.getInstance();
                    DishConfHolder confHolder = DishConfHolder.getInstance();

                    @Override
                    public void onSubscribe(@NonNull Disposable d) {

                    }

                    @Override
                    public void onNext(@NonNull Dish dish) {
                        holder.put(dish.getDish_guid(), dish);
                        if (TextUtils.isEmpty(dish.getTxt1()))
                            return;
                        if (confHolder.containsKey(dish.getTxt1())) {
                            confHolder.get(dish.getTxt1()).add(dish);
                        } else {
                            List<Dish> dishes = new ArrayList<>();
                            dishes.add(dish);
                            confHolder.put(dish.getTxt1(), dishes);
                        }
                    }

                    @Override
                    public void onError(@NonNull Throwable e) {
                        Logger.t(TAG).e(e.getMessage());
                        if (checkRefrence(mView)) {
                            loadFailed(mView, e.getMessage());
                        }
                    }

                    @Override
                    public void onComplete() {
                        loadDesignerData();
                    }
                });
    }

    /**
     * Methor Name:loadMenuTypeData<br/>
     * Package Name:com.wanhe.mealbookmodule.presenter<br/>
     * Date:2017/8/1 15:32<br/>
     * author:chendeji<br/>
     * desc: 用于加载菜品数据分类的操作<br/>
     * Copyright (c) 2017/8/1, 781571323@qq.com All Rights Reserved.
     *
     * @param
     * @return
     *
     */
    private void loadMenuTypeData() {
        if (ObjectUtil.checkObject(mTypeAdapter)) {
            final String designData = SPUtils.getDesign();
            if (TextUtils.isEmpty(designData)) {
                return;
            }
            Observable.just(designData).flatMap(new Function<String, ObservableSource<DesignEntity>>() {
                @Override
                public ObservableSource<DesignEntity> apply(@NonNull String s) throws Exception {
                    Gson gson = new Gson();
                    DesignEntity designEntity = gson.fromJson(s, DesignEntity.class);
                    return Observable.just(designEntity);
                }
            }).flatMap(new Function<DesignEntity, ObservableSource<CatalogViewModel>>() {
                @Override
                public ObservableSource<CatalogViewModel> apply(@NonNull DesignEntity designEntity) throws Exception {
                    return Observable.fromIterable(designEntity.catalogs);
                }
            }).filter(new Predicate<CatalogViewModel>() {
                @Override
                public boolean test(@NonNull CatalogViewModel catalogViewModel) throws Exception {
                    List<PageViewModel> pages = catalogViewModel.getPages();
                    return pages != null && pages.size() > 0;
                }
            }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<CatalogViewModel>() {
                List<CatalogViewModel> cataloges = new ArrayList<>();

                @Override
                public void onSubscribe(@NonNull Disposable d) {

                }

                @Override
                public void onNext(@NonNull CatalogViewModel catalogViewModel) {
                    cataloges.add(catalogViewModel);
                }

                @Override
                public void onError(@NonNull Throwable e) {
                    Logger.t(TAG).i(e.getMessage());
                }

                @Override
                public void onComplete() {
                    mTypeAdapter.refresh(cataloges);
                    loaded(mView);
                }
            });
        }
    }

    private void loadDesignerData() {
        /**
         *
         * 获取朝勋接口拿到的缓存数据，然后进行解析
         *
         * @author 陈德基
         * @time 2017/6/22 17:20
         */

        final String designData = SPUtils.getDesign();
        if (TextUtils.isEmpty(designData)) {
            loadFailed(mView, "设计器数据为空");
            return;
        }

        Observable.just(designData).flatMap(new Function<String, ObservableSource<DesignEntity>>() {
            @Override
            public ObservableSource<DesignEntity> apply(@NonNull String s) throws Exception {
                Gson gson = new Gson();
                DesignEntity designEntity = gson.fromJson(s, DesignEntity.class);
                return Observable.just(designEntity);
            }
        }).flatMap(new Function<DesignEntity, ObservableSource<CatalogViewModel>>() {
            @Override
            public ObservableSource<CatalogViewModel> apply(@NonNull DesignEntity designEntity)
                    throws Exception {
                List<DesignEntity.DSFilesGroup> files = designEntity.files;
                FileHolder instance = FileHolder.getInstance();
                /**
                 * 将设计器缓存起来，用于后期的方便查找
                 *
                 * @author 陈德基
                 * @time 2017/7/10 16:31
                 */
                for (int i = 0; i < files.size(); i++) {
                    DesignEntity.DSFilesGroup group = files.get(i);
                    for (int j = 0; j < group.getFiles().size(); j++) {
                        DSFile file = group.getFiles().get(j);
                        instance.put(file.getFid(), file);
                    }
                }
                return Observable.fromIterable(designEntity.catalogs);
            }
        }).filter(new Predicate<CatalogViewModel>() {
            @Override
            public boolean test(@NonNull CatalogViewModel catalogViewModel) throws Exception {
                List<PageViewModel> pages = catalogViewModel.getPages();
                boolean isUserfulPage = pages != null && pages.size() > 0;
                if (isUserfulPage){
                    for (int i = 0; i < pages.size(); i++) {
                        pages.get(i).setTid(catalogViewModel.getId());
                    }
                }
                return isUserfulPage;
            }
        }).flatMap(new Function<CatalogViewModel, ObservableSource<PageViewModel>>() {
            @Override
            public ObservableSource<PageViewModel> apply(@NonNull CatalogViewModel catalogViewModel)
                    throws Exception {

                return Observable.fromIterable(catalogViewModel.getPages());
            }
        }).filter(new Predicate<PageViewModel>() {
            CustomPageHolder holder = CustomPageHolder.getInstance();

            @Override
            public boolean test(@NonNull PageViewModel model) throws Exception {
                boolean result = model.getType().equals("page");
                if (!result) {
                    /**
                     * 缓存特殊的页面数据
                     *
                     * @author 陈德基
                     * @time 2017/7/13 17:38
                     */
                    List<ViewItem> items = model.getItems();
                    List<ViewItem> tempItems = new ArrayList<>();
                    transPageModelData(model, items, tempItems);
                    holder.put(model.getPid(), model);
                }
                return result;
            }
        }).flatMap(new Function<PageViewModel, ObservableSource<PageViewModel>>() {
            @Override
            public ObservableSource<PageViewModel> apply(@NonNull PageViewModel model)
                    throws Exception {
                List<ViewItem> items = model.getItems();
                List<ViewItem> tempItems = new ArrayList<>();
                transPageModelData(model, items, tempItems);
                return Observable.just(model);
            }
        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<PageViewModel>() {
                    List<PageViewModel> models = new ArrayList<>();

                    @Override
                    public void onSubscribe(@NonNull Disposable d) {

                    }

                    @Override
                    public void onNext(@NonNull PageViewModel model) {
                        models.add(model);
                    }

                    @Override
                    public void onError(@NonNull Throwable e) {
                        Logger.t(TAG).e(e.getMessage());
                        if (checkRefrence(mView)) {
                            loadFailed(mView, e.getMessage());
                        }
                    }

                    @Override
                    public void onComplete() {
                        refresh(mPagerAdapter, models);
                        loadMenuTypeData();
                        getSalloutData();
                    }
                });
    }

    /**
     * Methor Name:transPageModelData<br/>
     * Package Name:com.wanhe.mealbookmodule.presenter<br/>
     * Date:2017/7/15 15:43<br/>
     * author:chendeji<br/>
     * desc: 转换数据<br/>
     * Copyright (c) 2017/7/15, 781571323@qq.com All Rights Reserved.
     *
     * @param
     * @return
     */
    private void transPageModelData(@NonNull PageViewModel model, List<ViewItem> items,
                                    List<ViewItem> tempItems) {
        if (ObjectUtil.checkObjectList(items)) {
            for (int i = 0; i < items.size(); i++) {
                ViewItem viewItem = items.get(i);
                String type = viewItem.getType();
                if (type.equals(ViewItem.VIEW_TYPE_ITEM)
                        || type.equals(ViewItem.VIEW_TYPE_VIRTUAL)) {
                    /**
                     * 需要将里面的控件全部转化
                     *
                     * @author 陈德基
                     * @time 2017/7/10 17:26
                     */
                    ViewItem.ViewPort hit = viewItem.getHit();
                    ViewItem hitItem = generViewItem(viewItem, hit);
                    hitItem.setType("hit");
                    tempItems.add(hitItem);

                    ViewItem.ViewPort name = viewItem.getNametxt();
                    ViewItem nameItem = generViewItem(viewItem, name);
                    nameItem.setType("name");
                    tempItems.add(nameItem);

                    ViewItem.ViewPort plus = viewItem.getPlus();
                    ViewItem plusItem = generViewItem(viewItem, plus);
                    plusItem.setType("plus");
                    tempItems.add(plusItem);

                    ViewItem.ViewPort price1 = viewItem.getPrice1();
                    ViewItem price1Item = generViewItem(viewItem, price1);
                    price1Item.setType("price1");
                    tempItems.add(price1Item);

                    ViewItem.ViewPort price2 = viewItem.getPrice2();
                    ViewItem price2Item = generViewItem(viewItem, price2);
                    price2Item.setType("price2");
                    tempItems.add(price2Item);

                    ViewItem.ViewPort txt1 = viewItem.getTxt1();
                    ViewItem txt1Item = generViewItem(viewItem, txt1);
                    txt1Item.setType("txt1");
                    tempItems.add(txt1Item);

                } else {
                    tempItems.add(viewItem);
                }
            }
            model.setItems(tempItems);
        }
    }

    private void getSalloutData() {
        /**
         * 通过获取朝勋缓存的售罄数据进行缓存
         *
         * @author 陈德基
         * @time 2017/7/12 10:21
         */
        String sallOut = SPUtils.getSallOutData();
        Observable.just(sallOut).flatMap(new Function<String, ObservableSource<SallOutDish>>() {
            @Override
            public ObservableSource<SallOutDish> apply(@NonNull String s) throws Exception {
                Gson gson = new Gson();
                SellOutResultEntity resultEntity = gson.fromJson(s, SellOutResultEntity.class);
                if (ObjectUtil.checkObject(resultEntity)) {
                    if (resultEntity.resultType == BaseResultEntity.SUCCESS) {
                        List<SallOutDish> sallOutDishs = resultEntity.warnDishes;
                        return Observable.fromIterable(sallOutDishs);
                    }
                }
                return null;
            }
        }).subscribeOn(Schedulers.io()).observeOn(Schedulers.io())
                .subscribe(new Consumer<SallOutDish>() {
                    SallOutHolder holder = SallOutHolder.getInstance();

                    @Override
                    public void accept(@NonNull SallOutDish sallOutDish) throws Exception {
                        holder.put(sallOutDish.getDishID(), sallOutDish);
                    }
                });
    }

    private ViewItem generViewItem(ViewItem viewItem, ViewItem.ViewPort viewPort) {
        ViewItem item = new ViewItem();
        item.setCid(viewItem.getCid());
        item.setName(viewItem.getName());
        item.setId(viewItem.getId());
        item.setNametxt(viewItem.getNametxt());
        item.setVisible(viewPort == null ? false : viewPort.isVisible());
        item.setEvents(viewItem.getEvents());
        item.setCustom(viewItem.getCustom());
        item.setViewport(viewPort);
        item.setTid(viewItem.getTid());
        return item;
    }

}
